// API请求工具函数
import axios, { AxiosInstance, AxiosRequestConfig, AxiosError, AxiosResponse } from 'axios'
import { getAuthInfo, clearAuthInfo } from './storage'

// API基础URL
const BASE_URL = '/api'

// 创建axios实例
export const createApiClient = (): AxiosInstance => {
  const api = axios.create({
    baseURL: BASE_URL,
    timeout: 10000,
    headers: {
      'Content-Type': 'application/json'
    }
  })

  // 请求拦截器
  api.interceptors.request.use(
    (config) => {
      const { token } = getAuthInfo()
      if (token) {
        config.headers.Authorization = `Bearer ${token}`
      }
      return config
    },
    (error) => {
      return Promise.reject(error)
    }
  )

  // 响应拦截器
  api.interceptors.response.use(
    (response) => {
      return response
    },
    (error: AxiosError) => {
      handleRequestError(error)
      return Promise.reject(error)
    }
  )

  return api
}

// 定义错误响应数据接口
interface ErrorResponseData {
  errors?: Record<string, string[]>
  message?: string
}

// 错误处理函数
const handleRequestError = (error: AxiosError): void => {
  if (error.response) {
    // 服务器返回错误状态码
    const { status, data } = error.response as AxiosResponse<ErrorResponseData>
    
    switch (status) {
      case 401:
        // 未授权，清除认证信息并跳转到登录页
        clearAuthInfo()
        window.location.href = '/login'
        break
      case 403:
        // 拒绝访问，显示权限不足提示
        showErrorMessage('权限不足，请联系管理员')
        break
      case 404:
        // 资源不存在
        showErrorMessage('请求的资源不存在')
        break
      case 422:
        // 验证错误
        if (data?.errors) {
          const errorMessages = Object.values(data.errors)
            .flat()
            .join('\n')
          showErrorMessage(errorMessages)
        }
        break
      case 500:
        // 服务器错误
        showErrorMessage('服务器内部错误，请稍后重试')
        break
      default:
        showErrorMessage(data?.message || `请求失败：${status}`)
        break
    }
  } else if (error.request) {
    // 请求发出但没有收到响应
    showErrorMessage('网络错误，请检查网络连接')
  } else {
    // 请求配置错误
    showErrorMessage(`请求配置错误：${error.message}`)
  }
}

// 显示错误消息
const showErrorMessage = (message: string): void => {
  // 这里可以集成UI框架的消息组件，如Element Plus的ElMessage
  console.error('API错误:', message)
  
  // 临时使用alert显示错误，实际项目中应替换为更友好的UI组件
  // alert(message)
}

// 封装GET请求
export const get = async <T = any>(
  url: string,
  params?: any,
  config?: AxiosRequestConfig
): Promise<T> => {
  const api = createApiClient()
  const response = await api.get<T>(url, { params, ...config })
  return response as unknown as T
}

// 封装POST请求
export const post = async <T = any>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig
): Promise<T> => {
  const api = createApiClient()
  const response = await api.post<T>(url, data, config)
  return response as unknown as T
}

// 封装PUT请求
export const put = async <T = any>(
  url: string,
  data?: any,
  config?: AxiosRequestConfig
): Promise<T> => {
  const api = createApiClient()
  const response = await api.put<T>(url, data, config)
  return response as unknown as T
}

// 封装DELETE请求
export const del = async <T = any>(
  url: string,
  config?: AxiosRequestConfig
): Promise<T> => {
  const api = createApiClient()
  const response = await api.delete<T>(url, config)
  return response as unknown as T
}

// 封装上传文件请求
export const upload = async <T = any>(
  url: string,
  file: File,
  fileName: string = 'file',
  onUploadProgress?: (progressEvent: any) => void
): Promise<T> => {
  const formData = new FormData()
  formData.append(fileName, file)
  
  const config: AxiosRequestConfig = {
    headers: {
      'Content-Type': 'multipart/form-data'
    },
    onUploadProgress
  }
  
  const api = createApiClient()
  const response = await api.post<T>(url, formData, config)
  return response as unknown as T
}

// 封装下载文件请求
export const download = async (
  url: string,
  params?: any,
  fileName?: string
): Promise<void> => {
  const api = axios.create({
    baseURL: BASE_URL,
    timeout: 60000,
    responseType: 'blob',
    headers: {
      'Content-Type': 'application/json'
    }
  })
  
  const { token } = getAuthInfo()
  if (token) {
    api.defaults.headers.common['Authorization'] = `Bearer ${token}`
  }
  
  const response = await api.get(url, { params })
  const blob = response.data
  const urlBlob = window.URL.createObjectURL(new Blob([blob]))
  const link = document.createElement('a')
  link.href = urlBlob
  link.setAttribute('download', fileName || getFileNameFromHeaders(response.headers))
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  window.URL.revokeObjectURL(urlBlob)
}

// 从响应头中提取文件名
const getFileNameFromHeaders = (headers: any): string => {
  const contentDisposition = headers['content-disposition']
  if (contentDisposition) {
    const matches = /filename[^;=]*=((['"]).*?\2|[^;]*)/.exec(contentDisposition)
    if (matches != null && matches[1]) {
      return matches[1].replace(/['"]/g, '')
    }
  }
  return 'download'
}